/*[INCLUDE-IF JAVA_SPEC_VERSION >= 8]*/
/*
 * Copyright IBM Corp. and others 2012
 *
 * This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License 2.0 which accompanies this
 * distribution and is available at https://www.eclipse.org/legal/epl-2.0/
 * or the Apache License, Version 2.0 which accompanies this distribution and
 * is available at https://www.apache.org/licenses/LICENSE-2.0.
 *
 * This Source Code may also be made available under the following
 * Secondary Licenses when the conditions for such availability set
 * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
 * General Public License, version 2 with the GNU Classpath
 * Exception [1] and GNU General Public License, version 2 with the
 * OpenJDK Assembly Exception [2].
 *
 * [1] https://www.gnu.org/software/classpath/license.html
 * [2] https://openjdk.org/legal/assembly-exception.html
 *
 * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
 */

package com.ibm.oti.vm;

import java.util.Properties;

/*[IF JAVA_SPEC_VERSION >= 9]*/
import jdk.internal.reflect.ConstantPool;
/*[ELSE] JAVA_SPEC_VERSION >= 9 */
import sun.reflect.ConstantPool;
/*[ENDIF] JAVA_SPEC_VERSION >= 9 */

/**
 * Interface to allow privileged access to classes
 * from outside the java.lang package. Based on sun.misc.SharedSecrets
 * implementation.
 */
public interface VMLangAccess {
/*[IF JAVA_SPEC_VERSION >= 9]*/
	/**
	 * Answer the platform class loader.
	 */
	public ClassLoader getPlatformClassLoader();
/*[ENDIF] JAVA_SPEC_VERSION >= 9 */

	/**
	 * Uses native to find and load a class using the VM
	 *
	 * @return 		java.lang.Class
	 *					the class or null.
	 * @param 		className String
	 *					the name of the class to search for.
	 * @param		classLoader
	 *					the classloader to do the work
	 */
	public Class<?> findClassOrNullHelper(String className, ClassLoader classLoader);

	/**
	 * Answer the extension class loader.
	 */
	public ClassLoader getExtClassLoader();

	/**
	 * Returns true if parent is the ancestor of child.
	 * Parent and child must not be null.
	 */
	/*[PR CMVC 191554] Provide access to ClassLoader methods to improve performance */
	public boolean isAncestor(java.lang.ClassLoader parent, java.lang.ClassLoader child);

	/**
	 * Returns the ClassLoader off clazz.
	 */
	/*[PR CMVC 191554] Provide access to ClassLoader methods to improve performance */
	public java.lang.ClassLoader getClassloader(java.lang.Class clazz);

	/**
	 * Returns the package name for a given class.
	 */
	/*[PR CMVC 191554] Provide access to ClassLoader methods to improve performance */
	public java.lang.String getPackageName(java.lang.Class clazz);

	/**
	 * Returns a MethodHandle cache for a given class.
	 */
	public java.lang.Object getMethodHandleCache(java.lang.Class<?> clazz);

	/**
	 * Set a MethodHandle cache to a given class.
	 */
	public java.lang.Object setMethodHandleCache(java.lang.Class<?> clazz, java.lang.Object object);

	/**
	 * Returns a {@code java.util.Map} from method descriptor string to the equivalent {@code MethodType} as generated by {@code MethodType.fromMethodDescriptorString}.
	 * @param loader The {@code ClassLoader} used to get the MethodType.
	 * @return A {@code java.util.Map} from method descriptor string to the equivalent {@code MethodType}.
	 */
	public java.util.Map<String, java.lang.invoke.MethodType> getMethodTypeCache(ClassLoader loader);

	/**
	 *	Provide internal access to the system properties without going through SecurityManager
	 *
	 *  Important notes:
	 *  	1. This API must NOT be exposed to application code directly or indirectly;
	 *  	2. This method can only be used to retrieve system properties for internal usage,
	 *  		i.e., there is no security exception expected;
	 *  	3. If there is an application caller in the call stack, AND the application caller(s)
	 *  		have to be check for permission to retrieve the system properties specified,
	 *  		then this API should NOT be used even though the immediate caller is in boot strap path.
	 *
	 * @return the system properties
	 */
	public Properties internalGetProperties();

	/*[IF JAVA_SPEC_VERSION == 8]*/
	/**
	 * Returns the system packages for the bootloader
	 * @return An array of packages defined by the bootloader
	 */
	public Package[] getSystemPackages();

	/**
	 * Returns the system package for the 'name'
	 * @param name must not be null
	 * @return The package
	 */
	public Package getSystemPackage(String name);
	/*[ENDIF] JAVA_SPEC_VERSION == 8 */

	/**
	 * Returns an InternalConstantPool object.
	 *
	 * @param addr - the native addr of the J9ConstantPool
	 * @return An InternalConstantPool object
	 */
	public Object createInternalConstantPool(long addr);

	/**
	 * Returns a ConstantPool object
	 *
	 * @param internalConstantPool An object ref to an InternalConstantPool
	 * @return ConstantPool instance
	 */
	public ConstantPool getConstantPool(Object internalConstantPool);

	/**
	 * Returns an InternalConstantPool object from a J9Class address. The ConstantPool
	 * natives expect an InternalConstantPool as the constantPoolOop parameter.
	 *
	 * @param j9class the native address of the J9Class
	 * @return InternalConstantPool a wrapper for a j9constantpool
	 */
	public Object getInternalConstantPoolFromJ9Class(long j9class);

	/**
	 * Returns an InternalConstantPool object from a Class. The ConstantPool
	 * natives expect an InternalConstantPool as the constantPoolOop parameter.
	 *
	 * @param clazz the Class to fetch the constant pool from
	 * @return an InternalConstantPool wrapper for a j9constantpool
	 */
	public Object getInternalConstantPoolFromClass(Class clazz);

	/*[IF JAVA_SPEC_VERSION >= 9]*/
	/**
	 * Adds a class's package its classloader's package table.
	 * This is typically used when a class is defined without using ClassLoader.defineClass().
	 * @param newClass newly defined class
	 * @param loader classloader used to define the class
	 */
	public void addPackageToList(Class<?> newClass, ClassLoader loader);
	/*[ENDIF] JAVA_SPEC_VERSION >= 9 */

	/**
	 * Create a thread that it has runnable as its run object, has threadName as its name, has contextClassLoader as its context ClassLoader,
	 * has an option to be part of system thread group, has an option to inherit ThreadLocals or not, and has an option to set isDaemon.
	 *
	 * @param       runnable                A java.lang.Runnable whose method <code>run</code> will be executed by the new Thread
	 * @param       threadName              Name for the Thread being created
	 * @param       isSystemThreadGroup     A boolean indicating whether the thread to be created belongs to the system thread group
	 * @param       inheritThreadLocals     A boolean indicating whether to inherit initial values for inheritable thread-local variables
	 * @param       isDaemon                Indicates whether or not the Thread being created is a daemon thread
	 * @param       contextClassLoader      The context ClassLoader
	 *
	 * @return      A java.lang.Thread created
	 */
	public Thread createThread(Runnable runnable, String threadName, boolean isSystemThreadGroup, boolean inheritThreadLocals, boolean isDaemon, ClassLoader contextClassLoader);


	/**
	 * Prepare the passed in class
	 *
	 * @param theClass The class to prepare
	 */
	public void prepare(Class<?> theClass);

	/*[IF JAVA_SPEC_VERSION >= 11]*/
	/**
	 * Returns whether the classloader name should be included in the stack trace for the provided StackTraceElement.
	 *
	 * @param element The StackTraceElement to check
	 * @return true if the classloader name should be included, false otherwise
	 */
	public boolean getIncludeClassLoaderName(StackTraceElement element);

	/**
	 * Returns whether the module version should be included in the stack trace for the provided StackTraceElement.
	 *
	 * @param element The StackTraceElement to check
	 * @return true if the module version should be included, false otherwise
	 */
	public boolean getIncludeModuleVersion(StackTraceElement element);
	/*[ENDIF] JAVA_SPEC_VERSION >= 11*/
}
